package network;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

//站在服务器的角度：
//源IP：服务器程序所在主机的IP
//源端口：手动指定的端口【服务器绑定的端口】
//目的IP：包含在收到的数据报中【客户端的IP】
//目的端口：包含在收到的数据报中【客户端的端口】
//协议类型：UDP
public class UdpEchoServer {
    // 进行网络编程时，第一步就需要先准备好 socket 实例。
    // 这是进行网络编程的大前提。
    private DatagramSocket socket = null;

    // port 是 服务器的端口号
    public UdpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }

    // 启动服务器
    public void start() throws IOException {
        System.out.println("启动服务器");
        // UDP 是不需要建立连接的，直接 接收客户端发来的数据 即可。
        while(true){
            //1、读取客户端发来的请求
            DatagramPacket datagramPacket= new DatagramPacket(new byte[1024],1024);
            socket.receive(datagramPacket);//为了接收数据，需要先准备好一个空的DatagramPacket对象，有receive来填充数据
            // 将 datagramPacket 解析成一个 String
            String request = new String(datagramPacket.getData(),0,datagramPacket.getLength(),"UTF-8");

            //2、根据请求计算响应（由于咱们这是一个回显服务，这一步就可以省略了）
            String response = process(request);
            //3、把响应写回客户端
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,
                    datagramPacket.getSocketAddress());
            socket.send(responsePacket);

            // 打印具体 IP、端口、请求、响应
            System.out.printf("[%s:%d] request: %s,response: %s\n",
                    datagramPacket.getAddress().toString(),// 客户端IP
                    datagramPacket.getPort(),// 客户端端口号
                    request,//请求
                    response);// 响应
        }
    }
    // 由于是回显服务，所以响应就和请求一样
    //但是实际上，对于一个真实的服务器来说，这个过程（根据请求计算响应），是最复杂的！
    // 为了实现这个过程，可能需要几万行，甚至几十万行代码。。。
    public String process(String request){
        return  request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }
}
